Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"error: initializer element is not constant" when trying make julia #57440

Open
digital-carver opened this issue Feb 17, 2025 · 4 comments
Open
Labels
building Build system, or building Julia or its dependencies

Comments

@digital-carver
Copy link
Contributor

After cloning in the latest master on my WSL OpenSUSE Tumbleweed, running make results in:

    CC src/ast.o
    CC src/gc-stock.o
/home/sundar/foss/julia/src/gc-stock.c:144:34: error: initializer element is not constant
 static uint64_t old_alloc_diff = default_collect_interval;
                                  ^~~~~~~~~~~~~~~~~~~~~~~~
/home/sundar/foss/julia/src/gc-stock.c:145:34: error: initializer element is not constant
 static uint64_t old_freed_diff = default_collect_interval;
                                  ^~~~~~~~~~~~~~~~~~~~~~~~
make[1]: *** [Makefile:261: gc-stock.o] Error 1
make: *** [Makefile:108: julia-src-release] Error 2

I have gcc and g++ both version 7.5.0, along with the other tools mentioned here.

The only other issues with this error that I can find are this (which I don't understand tbh), and this (which is about Clang pretending to be gcc, doesn't seem relevant here). Seeing as this doesn't seem a commonly reported error, what element of my setup is the likely reason for this, and how can I fix it?

@giordano
Copy link
Contributor

@vtjnash
Copy link
Member

vtjnash commented Feb 17, 2025

It looks like we still document gcc >= 7.1, but since we don't test for that, it looks like that version didn't correctly handle this constexpr (AFAIK, they are considered an implementation-defined behavior, since C still has not yet standardized whether constants are allowed to be used, so it is not yet possible to define what it means to write standards-compliant code if it uses any constants). PRs welcome to alter that code to some form that will be accepted by GCC 7.5.0 though

@digital-carver
Copy link
Contributor Author

I'm not a C person, but there seem to be three ways around this:

Make the variables non-static and local
diff --git a/src/gc-stock.c b/src/gc-stock.c
index 3d3bc9f485..3885e335c1 100644
--- a/src/gc-stock.c
+++ b/src/gc-stock.c
@@ -141,8 +141,6 @@
 static uint64_t old_pause_time = 1e7; // 10 ms
 static uint64_t old_mut_time = 1e9; // 1 second
 static uint64_t old_heap_size = 0;
-static uint64_t old_alloc_diff = default_collect_interval;
-static uint64_t old_freed_diff = default_collect_interval;
 static uint64_t gc_end_time = 0;
 static int thrash_counter = 0;
 static int thrashing = 0;
@@ -3028,6 +3026,8 @@
 
     jl_gc_markqueue_t *mq = &ptls->gc_tls.mark_queue;
 
+    uint64_t old_alloc_diff = default_collect_interval;
+    uint64_t old_freed_diff = default_collect_interval;
     uint64_t gc_start_time = jl_hrtime();
     uint64_t mutator_time = gc_end_time == 0 ? old_mut_time : gc_start_time - gc_end_time;
     uint64_t before_free_heap_size = jl_atomic_load_relaxed(&gc_heap_stats.heap_size);

old_alloc_diff and old_freed_diff are used only inside the _jl_gc_collect function, so making them local variables to that function and removing the static annotation solves the issue. The only minor downside AFAICT is that this separates them from the other old_ variables, so may need a connecting comment.


`#define` the constant
diff --git a/src/gc-stock.c b/src/gc-stock.c
index 3d3bc9f485..425ae1ec86 100644
--- a/src/gc-stock.c
+++ b/src/gc-stock.c
@@ -123,13 +123,13 @@
 // under this limit, but we will go above it rather than halting.
 #ifdef _P64
 typedef uint64_t memsize_t;
-static const size_t default_collect_interval = 5600 * 1024 * sizeof(void*);
+#define DEFAULT_COLLECT_INTERVAL (5600 * 1024 * sizeof(void*))
 static size_t total_mem;
 // We expose this to the user/ci as jl_gc_set_max_memory
 static memsize_t max_total_memory = (memsize_t) 2 * 1024 * 1024 * 1024 * 1024 * 1024;
 #else
 typedef uint32_t memsize_t;
-static const size_t default_collect_interval = 3200 * 1024 * sizeof(void*);
+#define DEFAULT_COLLECT_INTERVAL (3200 * 1024 * sizeof(void*))
 // Work really hard to stay within 2GB
 // Alternative is to risk running out of address space
 // on 32 bit architectures.
@@ -141,8 +141,8 @@
 static uint64_t old_pause_time = 1e7; // 10 ms
 static uint64_t old_mut_time = 1e9; // 1 second
 static uint64_t old_heap_size = 0;
-static uint64_t old_alloc_diff = default_collect_interval;
-static uint64_t old_freed_diff = default_collect_interval;
+static uint64_t old_alloc_diff = DEFAULT_COLLECT_INTERVAL;
+static uint64_t old_freed_diff = DEFAULT_COLLECT_INTERVAL;
 static uint64_t gc_end_time = 0;
 static int thrash_counter = 0;
 static int thrashing = 0;
@@ -1312,7 +1312,7 @@
         }
         n_pages_seen++;
         // keep the last few pages around for a while
-        if (n_pages_seen * GC_PAGE_SZ <= default_collect_interval) {
+        if (n_pages_seen * GC_PAGE_SZ <= DEFAULT_COLLECT_INTERVAL) {
             push_lf_back(&tmp, pg);
             continue;
         }
@@ -3251,8 +3251,8 @@
 
         // compute some guardrails values
         uint64_t min_target_allocs = heap_size / 20; // minimum 5% of current heap
-        if (min_target_allocs < default_collect_interval / 8) // unless the heap is small
-            min_target_allocs = default_collect_interval / 8;
+        if (min_target_allocs < DEFAULT_COLLECT_INTERVAL / 8) // unless the heap is small
+            min_target_allocs = DEFAULT_COLLECT_INTERVAL / 8;
         uint64_t max_target_allocs = overallocation(before_free_heap_size, heap_size, user_max);
         if (max_target_allocs < min_target_allocs)
             max_target_allocs = min_target_allocs;
@@ -3280,8 +3280,8 @@
         }
         // and set the heap detection threshold
         target_heap = target_allocs + heap_size;
-        if (target_heap < default_collect_interval) {
-            target_heap = default_collect_interval;
+        if (target_heap < DEFAULT_COLLECT_INTERVAL) {
+            target_heap = DEFAULT_COLLECT_INTERVAL;
             reason = " min heap";
         }
         jl_atomic_store_relaxed(&gc_heap_stats.heap_target, target_heap);
@@ -3686,8 +3686,8 @@
 
     arraylist_new(&finalizer_list_marked, 0);
     arraylist_new(&to_finalize, 0);
-    jl_atomic_store_relaxed(&gc_heap_stats.heap_target, default_collect_interval);
-    gc_num.interval = default_collect_interval;
+    jl_atomic_store_relaxed(&gc_heap_stats.heap_target, DEFAULT_COLLECT_INTERVAL);
+    gc_num.interval = DEFAULT_COLLECT_INTERVAL;
     gc_num.allocd = 0;
     gc_num.max_pause = 0;
     gc_num.max_memory = 0;

anonymous enum hack
diff --git a/src/gc-stock.c b/src/gc-stock.c
index 3d3bc9f485..aec502e7d2 100644
--- a/src/gc-stock.c
+++ b/src/gc-stock.c
@@ -123,13 +123,13 @@
 // under this limit, but we will go above it rather than halting.
 #ifdef _P64
 typedef uint64_t memsize_t;
-static const size_t default_collect_interval = 5600 * 1024 * sizeof(void*);
+enum { default_collect_interval = 5600 * 1024 * sizeof(void*) };
 static size_t total_mem;
 // We expose this to the user/ci as jl_gc_set_max_memory
 static memsize_t max_total_memory = (memsize_t) 2 * 1024 * 1024 * 1024 * 1024 * 1024;
 #else
 typedef uint32_t memsize_t;
-static const size_t default_collect_interval = 3200 * 1024 * sizeof(void*);
+enum { default_collect_interval = 3200 * 1024 * sizeof(void*) };
 // Work really hard to stay within 2GB
 // Alternative is to risk running out of address space
 // on 32 bit architectures.

This keeps the variables scopes as they are, but maybe a bit too clever, and changes default_collect_interval 's type into an int I believe.


All three of these lead to a successful compilation of gc-stock.o, but I can't test them beyond that - because, after some linking, I run into (I believe unrelated) Segmentation fault errors and so don't end up with a successful julia build to test.

Segmentation fault in expression starting at boot.jl:283
    CC src/gc-stock.o
    LINK usr/lib/libjulia-internal.so.1.13.0
    LINK usr/lib/libjulia-internal.so.1.13
    LINK usr/lib/libjulia-internal.so
    LINK usr/lib/libjulia-codegen.so.1.13.0
    LINK usr/lib/libjulia-codegen.so.1.13
    LINK usr/lib/libjulia-codegen.so
    JULIA usr/lib/julia/basecompiler.ji

[9890] signal 11 (1): Segmentation fault
in expression starting at boot.jl:283
_ZN4llvm9Intrinsic23matchIntrinsicSignatureEPNS_12FunctionTypeERNS_8ArrayRefINS0_13IITDescriptorEEERNS_15SmallVectorImplIPNS_4TypeEEE at /home/sundar/foss/julia/usr/bin/../lib/libLLVM.so.18.1jl (unknown line)
_ZN4llvm9Intrinsic25remangleIntrinsicFunctionEPNS_8FunctionE at /home/sundar/foss/julia/usr/bin/../lib/libLLVM.so.18.1jl (unknown line)
removeAddrspaces at /home/sundar/foss/julia/src/llvm-remove-addrspaces.cpp:411
run at /home/sundar/foss/julia/src/llvm-remove-addrspaces.cpp:424 [inlined]
run at /home/sundar/foss/julia/src/llvm-remove-addrspaces.cpp:450
run at /home/sundar/foss/julia/usr/include/llvm/IR/PassManagerInternal.h:89
_ZN4llvm11PassManagerINS_6ModuleENS_15AnalysisManagerIS1_JEEEJEE3runERS1_RS3_ at /home/sundar/foss/julia/usr/bin/../lib/libLLVM.so.18.1jl (unknown line)
run at /home/sundar/foss/julia/src/pipeline.cpp:740
operator() at /home/sundar/foss/julia/src/jitlayers.cpp:1581 [inlined]
withModuleDo<(anonymous namespace)::sizedOptimizerT<N>::operator()(llvm::orc::ThreadSafeModule) [with long unsigned int N = 4]::<lambda(llvm::Module&)> > at /home/sundar/foss/julia/usr/include/llvm/ExecutionEngine/Orc/ThreadSafeModule.h:136 [inlined]
operator() at /home/sundar/foss/julia/src/jitlayers.cpp:1542 [inlined]
operator() at /home/sundar/foss/julia/src/jitlayers.cpp:1694 [inlined]
addModule at /home/sundar/foss/julia/src/jitlayers.cpp:2153
jl_compile_codeinst_now at /home/sundar/foss/julia/src/jitlayers.cpp:626
jl_generate_fptr_for_unspecialized_impl at /home/sundar/foss/julia/src/jitlayers.cpp:997
jl_compile_method_internal at /home/sundar/foss/julia/src/gf.c:3009
_jl_invoke at /home/sundar/foss/julia/src/gf.c:3467 [inlined]
ijl_invoke at /home/sundar/foss/julia/src/gf.c:3482
jl_toplevel_eval_flex at /home/sundar/foss/julia/src/toplevel.c:1023
jl_parse_eval_all at /home/sundar/foss/julia/src/toplevel.c:1153
ijl_load_ at /home/sundar/foss/julia/src/toplevel.c:1197
ijl_load at /home/sundar/foss/julia/src/toplevel.c:1210
_finish_julia_init at /home/sundar/foss/julia/src/init.c:899
julia_init at /home/sundar/foss/julia/src/init.c:864
jl_repl_entrypoint at /home/sundar/foss/julia/src/jlapi.c:1118
main at /home/sundar/foss/julia/cli/loader_exe.c:58
__libc_start_call_main at /lib64/libc.so.6 (unknown line)
__libc_start_main at /lib64/libc.so.6 (unknown line)
_start at /home/abuild/rpmbuild/BUILD/glibc-2.38/csu/../sysdeps/x86_64/start.S:115
Allocations: 0 (Pool: 0; Big: 0); GC: 0
/bin/sh: line 1:  9890 Segmentation fault      (core dumped) JULIA_NUM_THREADS=1 /home/sundar/foss/julia/usr/bin/julia -C "native" --output-ji /home/sundar/foss/julia/usr/lib/julia/basecompiler.ji.tmp --startup-file=no --warn-overwrite=yes -g0 -O1 Base_compiler.jl --buildroot ./ --dataroot ../usr/share/
make[1]: *** [sysimage.mk:69: /home/sundar/foss/julia/usr/lib/julia/basecompiler.ji] Error 139
make: *** [Makefile:114: julia-sysimg-ji] Error 2

I can open a separate issue for this segfault if needed, and I can turn any of the diffs above into a PR if it seems like a usable solution.

@nsajko nsajko added the building Build system, or building Julia or its dependencies label Feb 18, 2025
@vtjnash
Copy link
Member

vtjnash commented Feb 18, 2025

The #define approach seems best. You may need USE_BINARYBUILDER=0 in Make.user, since I don't know if we necessarily build shards for and detect the compiler ABI correctly for an old compiler of that age.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
building Build system, or building Julia or its dependencies
Projects
None yet
Development

No branches or pull requests

4 participants