diff --git a/src/class/cc.c b/src/class/cc.c index e0451697..efd78a0c 100644 --- a/src/class/cc.c +++ b/src/class/cc.c @@ -60,7 +60,7 @@ static void get_include_deps(compile_task_t* task, char* cc) { // -MT "": Exclude the source file from the output. // TODO Can we do this in parallel easily with 'cmd_exec_async'? - cmd_t __attribute__((cleanup(cmd_free))) cmd; + cmd_t __attribute__((cleanup(cmd_free))) cmd = {0}; cmd_create(&cmd, cc, "-fdiagnostics-color=always", "-MM", "-MT", "", task->src, NULL); add_flags(&cmd, task); diff --git a/src/frugal.c b/src/frugal.c index 4a5bec74..05d5120a 100644 --- a/src/frugal.c +++ b/src/frugal.c @@ -59,6 +59,9 @@ bool frugal_flags(flamingo_val_t* flags, char* out) { fclose(f); + // Note that we want to compare the order of these flags too, so just compare the strings. + // There could be some cases where flipping the order of flags could change the build, which is perhaps rare but let's not try to be too smart here. + if (strcmp(prev_flag_str, flag_str) != 0) { goto write_out; } diff --git a/tests/frugality.sh b/tests/frugality.sh new file mode 100644 index 00000000..3a86a80f --- /dev/null +++ b/tests/frugality.sh @@ -0,0 +1,174 @@ +#!/bin/sh + +. tests/common.sh + +# Regression test for the following PR: +# https://github.com/inobulles/bob/pull/70 + +# Make sure build.fl's Cc flags are correct. + +if [ $(uname) = Linux ]; then # XXX Linux is annoying. + sed -i 's/-std=c11/-std=c99/g' tests/frugality/build.fl +else + sed -i '' 's/-std=c11/-std=c99/g' tests/frugality/build.fl +fi + +# Clean up. + +BOB_PATH=tests/frugality/.bob +rm -rf $BOB_PATH + +# Functions for getting the mtimes of all cookies and preinstalled files. + +build() { + out=$(bob -C tests/frugality run 2>&1) + + if [ $? != 0 ]; then + echo "Build failed: $out" >&2 + exit 1 + fi +} + +get_mtimes() { + export src1_${1}mtime=$(date -r $BOB_PATH/bob/src1.c.cookie.6531c664ecf.o +%s) + export src2_${1}mtime=$(date -r $BOB_PATH/bob/src2.c.cookie.6531c665310.o +%s) + export linked_${1}mtime=$(date -r $BOB_PATH/bob/linker.link.cookie.33faaddbf5af8a68.l +%s) + + export obj1_${1}mtime=$(date -r $BOB_PATH/prefix/obj1.o +%s) + export obj2_${1}mtime=$(date -r $BOB_PATH/prefix/obj2.o +%s) + export bin_${1}mtime=$(date -r $BOB_PATH/prefix/bin +%s) +} + +update() { + # We're running here instead of just building (even if there's nothing to run). + # This is because we want the preinstallation step to run. + + build + get_mtimes "" + + # If the mtime of the installed file is less than that of the cookie, then it was not reinstalled, which is bad!. + + if [ $obj1_mtime -lt $src1_mtime ]; then + echo "obj1.o's cookie was updated, but it was not preinstalled." >&2 + exit 1 + fi + + if [ $obj2_mtime -lt $src2_mtime ]; then + echo "obj2.o's cookie was updated, but it was not preinstalled." >&2 + exit 1 + fi + + if [ $bin_mtime -lt $linked_mtime ]; then + echo "bin's cookie was updated, but it was not preinstalled." >&2 + exit 1 + fi + + # If the cookie was not updated, then it shouldn't have been preinstalled. + + export src1_updated= + export src2_updated= + export linked_updated= + + if [ $src1_mtime = $src1_prev_mtime ]; then + if [ $obj1_mtime -gt $obj1_prev_mtime ]; then + echo "obj1.o's cookie was not updated, but it was preinstalled." >&2 + exit 1 + fi + elif [ $src1_mtime -gt $src1_prev_mtime ]; then + src1_updated=true + else + echo "This is impossible." >&2 + exit 1 + fi + + if [ $src2_mtime = $src2_prev_mtime ]; then + if [ $obj2_mtime -gt $obj2_prev_mtime ]; then + echo "obj2.o's cookie was not updated, but it was preinstalled." >&2 + exit 1 + fi + elif [ $src2_mtime -gt $src2_prev_mtime ]; then + src2_updated=true + else + echo "This is impossible." >&2 + exit 1 + fi + + if [ $linked_mtime = $linked_prev_mtime ]; then + if [ $bin_mtime -gt $bin_prev_mtime ]; then + echo "bin's cookie was not updated, but it was preinstalled." >&2 + exit 1 + fi + elif [ $linked_mtime -gt $linked_prev_mtime ]; then + linked_updated=true + else + echo "This is impossible." >&2 + exit 1 + fi +} + +build # Run this once to populate .bob already. + +echo "Test 1: changing 'src2.c'." + +get_mtimes "prev_" +sleep 1 +touch tests/frugality/src2.c +update + +if [ "$src1_updated" = true ] || [ -z $src2_updated ] || [ -z $linked_updated ]; then + echo "Changing 'src2.c' failed." >&2 + exit 1 +fi + +echo "Test 2: changing both 'src1.c' and 'src2.c'." + +get_mtimes "prev_" +sleep 1 +touch tests/frugality/src1.c tests/frugality/src2.c +update + +if [ -z $src1_updated ] || [ -z $src2_updated ] || [ -z $linked_updated ]; then + echo "Changing 'src1.c' and 'src2.c' failed." >&2 + exit 1 +fi + +echo "Test 3: changing nothing." + +get_mtimes "prev_" +sleep 1 +update + +if [ $src1_updated ] || [ $src2_updated ] || [ $linked_updated ]; then + echo "Changing nothing failed." >&2 + exit 1 +fi + +echo "Test 4: changing 'src2.h'." + +get_mtimes "prev_" +sleep 1 +touch tests/frugality/src2.h +update + +if [ $src1_updated ] || [ -z $src2_updated ] || [ -z $linked_updated ]; then + echo "Changing 'src2.h' failed." >&2 + exit 1 +fi + +echo "Test 5: changing compilation flags for all source files." + +get_mtimes "prev_" +sleep 1 + +if [ $(uname) = Linux ]; then # XXX Linux is annoying. + sed -i 's/-std=c99/-std=c11/g' tests/frugality/build.fl +else + sed -i '' 's/-std=c99/-std=c11/g' tests/frugality/build.fl +fi + +update + +if [ -z $src1_updated ] || [ -z $src2_updated ] || [ -z $linked_updated ]; then + echo "Changing compilation flags failed." >&2 + exit 1 +fi diff --git a/tests/frugality/build.fl b/tests/frugality/build.fl new file mode 100644 index 00000000..82fd8c26 --- /dev/null +++ b/tests/frugality/build.fl @@ -0,0 +1,13 @@ +import bob + +let src1 = "src1.c" +let src2 = "src2.c" + +let obj = Cc(["-std=c11"]).compile([src1, src2]) +let linked = Linker([]).link(obj) + +install = { + obj[0]: "obj1.o", + obj[1]: "obj2.o", + linked: "bin", +} diff --git a/tests/frugality/src1.c b/tests/frugality/src1.c new file mode 100644 index 00000000..f15123c5 --- /dev/null +++ b/tests/frugality/src1.c @@ -0,0 +1,5 @@ +#include + +void fn(void) { + printf("B\n"); +} diff --git a/tests/frugality/src2.c b/tests/frugality/src2.c new file mode 100644 index 00000000..440a21ab --- /dev/null +++ b/tests/frugality/src2.c @@ -0,0 +1,10 @@ +#include "src2.h" +#include + +void fn(void); + +int main(void) { + printf(STR "\n"); + fn(); + return 0; +} diff --git a/tests/frugality/src2.h b/tests/frugality/src2.h new file mode 100644 index 00000000..e3703f37 --- /dev/null +++ b/tests/frugality/src2.h @@ -0,0 +1 @@ +#define STR "A"