aboutsummaryrefslogtreecommitdiffstats
path: root/build/4coder_byp/custom/4coder_build_commands.cpp
blob: 22a76db2e1a4a35279204618e6da0dc8847814eb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
4coder_build_commands.cpp - Commands for building.
*/

// TOP

static String_Const_u8
push_build_directory_at_file(Application_Links *app, Arena *arena, Buffer_ID buffer){
  String_Const_u8 result = {};
  String_Const_u8 file_name = push_buffer_file_name(app, arena, buffer);
  Temp_Memory restore_point = begin_temp(arena);
  String_Const_u8 base_name = push_buffer_base_name(app, arena, buffer);
  b32 is_match = string_match(file_name, base_name);
  end_temp(restore_point);
  if (!is_match){
    result = push_string_copy(arena, string_remove_last_folder(file_name));
  }
  return(result);
}

#if OS_WINDOWS

global String_Const_u8 standard_build_file_name_array[] = {
  str8_lit("build.bat"),
};
global String_Const_u8 standard_build_cmd_string_array[] = {
  str8_lit("build"),
};

#elif OS_LINUX || OS_MAC

global String_Const_u8 standard_build_file_name_array[] = {
  str8_lit("build.sh"),
  str8_lit("Makefile"),
};
global String_Const_u8 standard_build_cmd_string_array[] = {
  str8_lit("build.sh"),
  str8_lit("make"),
};

#else
#error OS needs standard search and build rules
#endif

static String_Const_u8
push_fallback_command(Arena *arena, String_Const_u8 file_name){
  return(push_u8_stringf(arena, "echo could not find %S", file_name));
}

static String_Const_u8
push_fallback_command(Arena *arena){
  return(push_fallback_command(arena, standard_build_file_name_array[0]));
}

global_const Buffer_Identifier standard_build_build_buffer_identifier = buffer_identifier(string_u8_litexpr("*compilation*"));

global_const u32 standard_build_exec_flags = CLI_OverlapWithConflict|CLI_SendEndSignal;

static void
standard_build_exec_command(Application_Links *app, View_ID view, String_Const_u8 dir, String_Const_u8 cmd){
  exec_system_command(app, view, standard_build_build_buffer_identifier,
                      dir, cmd,
                      standard_build_exec_flags);
}

function b32
standard_search_and_build_from_dir(Application_Links *app, View_ID view, String_Const_u8 start_dir){
  Scratch_Block scratch(app);

  // NOTE(allen): Search
  String_Const_u8 full_file_path = {};
  String_Const_u8 cmd_string  = {};
  for (i32 i = 0; i < ArrayCount(standard_build_file_name_array); i += 1){
    full_file_path = push_file_search_up_path(app, scratch, start_dir, standard_build_file_name_array[i]);
    if (full_file_path.size > 0){
      cmd_string = standard_build_cmd_string_array[i];
      break;
    }
  }

  b32 result = (full_file_path.size > 0);
  if (result){
    // NOTE(allen): Build
    String_Const_u8 path = string_remove_last_folder(full_file_path);
    String_Const_u8 command = push_u8_stringf(scratch, "\"%S/%S\"", path, cmd_string);
    b32 auto_save = def_get_config_b32(vars_save_string_lit("automatically_save_changes_on_build"));
    if (auto_save){
      save_all_dirty_buffers(app);
    }
    standard_build_exec_command(app, view, path, command);
    print_message(app, push_u8_stringf(scratch, "Building with: %S\n", full_file_path));
  }

  return(result);
}

// NOTE(allen): This searches first using the active file's directory,
// then if no build script is found, it searches from 4coders hot directory.
static void
standard_search_and_build(Application_Links *app, View_ID view, Buffer_ID active_buffer){
  Scratch_Block scratch(app);
  b32 did_build = false;
  String_Const_u8 build_dir = push_build_directory_at_file(app, scratch, active_buffer);
  if (build_dir.size > 0){
    did_build = standard_search_and_build_from_dir(app, view, build_dir);
  }
  if (!did_build){
    build_dir = push_hot_directory(app, scratch);
    if (build_dir.size > 0){
      did_build = standard_search_and_build_from_dir(app, view, build_dir);
    }
  }
  if (!did_build){
    standard_build_exec_command(app, view,
                                push_hot_directory(app, scratch),
                                push_fallback_command(scratch));
  }
}

CUSTOM_COMMAND_SIG(build_search)
CUSTOM_DOC("Looks for a build.bat, build.sh, or makefile in the current and parent directories.  Runs the first that it finds and prints the output to *compilation*.")
{
  View_ID view = get_active_view(app, Access_Always);
  Buffer_ID buffer = view_get_buffer(app, view, Access_Always);
  standard_search_and_build(app, view, buffer);
  block_zero_struct(&prev_location);
  lock_jump_buffer(app, string_u8_litexpr("*compilation*"));
}

static Buffer_ID
get_comp_buffer(Application_Links *app){
  return(get_buffer_by_name(app, string_u8_litexpr("*compilation*"), Access_Always));
}

static View_ID
get_or_open_build_panel(Application_Links *app){
  View_ID view = 0;
  Buffer_ID buffer = get_comp_buffer(app);
  if (buffer != 0){
    view = get_first_view_with_buffer(app, buffer);
  }
  if (view == 0){
    view = open_build_footer_panel(app);
  }
  return(view);
}

function void
set_fancy_compilation_buffer_font(Application_Links *app){
  Scratch_Block scratch(app);
  Buffer_ID buffer = get_comp_buffer(app);
  Font_Load_Location font = {};
  font.file_name = def_search_normal_full_path(scratch, str8_lit("fonts/Inconsolata-Regular.ttf"));
  set_buffer_face_by_font_load_location(app, buffer, &font);
}

function void
comp_error(Application_Links *app, String_Const_u8 error_text){
  Buffer_ID buffer_comp = buffer_identifier_to_id_create_out_buffer(app, buffer_identifier(string_u8_litexpr("*compilation*")));
  buffer_replace_range(app, buffer_comp, buffer_range(app, buffer_comp), error_text);
  block_zero_struct(&prev_location);
  lock_jump_buffer(app, buffer_comp);
  get_or_make_list_for_buffer(app, &global_heap, buffer_comp);
}

CUSTOM_COMMAND_SIG(build_in_build_panel)
CUSTOM_DOC("Looks for a build.bat, build.sh, or makefile in the current and parent directories.  Runs the first that it finds and prints the output to *compilation*.  Puts the *compilation* buffer in a panel at the footer of the current view.")
{
  View_ID view = get_active_view(app, Access_Always);
  Buffer_ID buffer = view_get_buffer(app, view, Access_Always);

  View_ID build_view = get_or_open_build_panel(app);

  standard_search_and_build(app, build_view, buffer);
#if 0
  set_fancy_compilation_buffer_font(app);
#endif

  block_zero_struct(&prev_location);
  lock_jump_buffer(app, string_u8_litexpr("*compilation*"));
}

CUSTOM_COMMAND_SIG(close_build_panel)
CUSTOM_DOC("If the special build panel is open, closes it.")
{
  close_build_footer_panel(app);
}

CUSTOM_COMMAND_SIG(change_to_build_panel)
CUSTOM_DOC("If the special build panel is open, makes the build panel the active panel.")
{
  View_ID view = get_or_open_build_panel(app);
  if (view != 0){
    view_set_active(app, view);
  }
}

// BOTTOM