IoLanguage / io

Io programming language. Inspired by Self, Smalltalk and LISP.
http://iolanguage.org
Other
2.67k stars 299 forks source link

Trouble Compiling Io on Alpine in Docker Container #433

Closed djscheuf closed 3 years ago

djscheuf commented 4 years ago

Long story short, I am trying to create a Docker Container/Image for Io. I'm using the common Alpine as the base, and have run into a pair of issues so far.

  1. Sys/sysctl.h does not appear to exist in Alpine.

Here's the error I am seeing:

[ 46%] Building C object libs/iovm/CMakeFiles/iovmall.dir/source/IoSystem.c.o
/src/io/libs/iovm/source/IoSystem.c:26:11: fatal error: sys/sysctl.h: No such file or directory
   26 | # include <sys/sysctl.h>
      |           ^~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [libs/iovm/CMakeFiles/iovmall.dir/build.make:555: libs/iovm/CMakeFiles/iovmall.dir/source/IoSystem.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:471: libs/iovm/CMakeFiles/iovmall.dir/all] Error 2make: *** [Makefile:172: all] Error 2
The command '/bin/sh -c bash ./build.sh' returned a non-zero code: 2

You should be able to reproduce the above issue using the following dockerfile:

FROM alpine:latest

RUN apk add git && \
    apk add bash && \
    apk add build-base && \
    apk add make && \
    apk add cmake && \
    rm -rf /var/lib/apt/lists/* && \
    rm /var/cache/apk/*
# installs git, bash, gcc, make, and cmake

WORKDIR /src
RUN git clone --recursive https://github.com/IoLanguage/io.git

WORKDIR /src/io
RUN mkdir build 
RUN bash ./build.sh

ENTRYPOINT [ "bash" ]

Copy those contents into a Dockerfile file, the open a command prompt in that folder. To execute that image run this command, assuming you have docker installed, and the daemon is running:

docker build -t io .

Near as I can make out, the particular dependency is being deprecated. And a handful of other libraries have resolved the issue by simply removing the dependency. I don't think that will work in this case, as doing so did not resolve the issue, at least not completely.

To at least run down what I could, I forked the main repo, and manually removed the include of <sys/sysctl.h> in /libs/iovm/IoSystem.c, which I used in the second struggle to see if it made a difference.

  1. Removing the dependency in #1, results in Linking Errors , specifically citing issues with swapcontext, makecontext, and get context

Basically when you run the make command you get the following error as you near the end of compiling:

[ 99%] Linking C executable ../_build/binaries/io
/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/bin/ld: ../_build/dll/libcoroutine.so: undefined reference to `swapcontext'
/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/bin/ld: ../_build/dll/libcoroutine.so: undefined reference to `makecontext'
/usr/lib/gcc/x86_64-alpine-linux-musl/9.3.0/../../../../x86_64-alpine-linux-musl/bin/ld: ../_build/dll/libcoroutine.so: undefined reference to `getcontext'
collect2: error: ld returned 1 exit status
make[2]: *** [tools/CMakeFiles/io.dir/build.make:108: _build/binaries/io] Error 1
make[1]: *** [CMakeFiles/Makefile2:528: tools/CMakeFiles/io.dir/all] Error 2
make: *** [Makefile:172: all] Error 2
The command '/bin/sh -c bash ./build.sh' returned a non-zero code: 2

You should be able to reproduce the above using the following Dockerfile:

FROM alpine:latest

RUN apk add git && \
    apk add bash && \
    apk add build-base && \
    apk add make && \
    apk add cmake && \
    rm -rf /var/lib/apt/lists/* && \
    rm /var/cache/apk/*
# installs git, bash, gcc, make, and cmake

WORKDIR /src
RUN git clone --recursive https://github.com/djscheuf/io.git

WORKDIR /src/io
RUN git checkout dev

RUN mkdir build 
RUN bash ./build.sh

ENTRYPOINT [ "bash" ]

Outstanding questions:

  1. Is Sys/sysctl.h necessary in the Alpine Environment?
  2. If yes, any guess as to why it was not already available given bash, gcc, and the cmake dependencies?
  3. If no, How should the '*context's be provided?

Thank you for your time and your help.

djscheuf commented 4 years ago

On a whim I check on the latest resolved issue, and found the last mention of a stable version was back from 2017, if I recall correctly. So I tried the build again pulling that tag. The results were not much better, complaining of about a missing something called 'Cairo' when calling cmake.

You could repro the issue I am seeing using the following dockerfile:

FROM alpine:latest

RUN apk add git && \
    apk add bash && \
    apk add build-base && \
    apk add make && \
    apk add cmake && \
    rm -rf /var/lib/apt/lists/* && \
    rm /var/cache/apk/*
# installs git, bash, gcc, make, and cmake

WORKDIR /src
RUN git clone --recursive https://github.com/IoLanguage/io.git

WORKDIR /src/io
RUN git checkout 2017.09.06

RUN mkdir build 
RUN bash ./build.sh

ENTRYPOINT [ "bash" ]

And while this Image may not be working on it's own, it might be closer to working as a container than perhaps working from latest.

djscheuf commented 4 years ago

After much tinkering, I am pleased to announce that I have a working Io docker image! I shifted from Alpine to Ubuntu, so I doubt the size is optimal, but it works!

Here's the dockerfile I used:

FROM ubuntu:latest

RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive \
    apt install -y tzdata && \
    apt-get install -y \
    build-essential \
    git \
    cmake

WORKDIR /src
RUN git clone --recursive https://github.com/IoLanguage/io.git

WORKDIR /src/io
RUN mkdir build 
WORKDIR /src/io/build
RUN cmake ..
RUN make
RUN make install

ENTRYPOINT [ "bash" ]

This image will get the current latest version of the io language in the repo, make, and install it. In theory you could use this image as the base for future images, into which you could import your io programs for use or running. I am considering where this file might best fit in the repository, so that I can contribute this to the community for future use.

stevedekorte commented 4 years ago

That's great, Dan. I can also add it to (or mention it on) the Io website when it's ready.

eli-schwartz commented 4 years ago

I'm very confused. The error here is that:

Near as I can make out, the particular dependency is being deprecated. And a handful of other libraries have resolved the issue by simply removing the dependency. I don't think that will work in this case, as doing so did not resolve the issue, at least not completely.

and thus, any linux distro with GNU libc 2.32 or greater cannot compile this. Moving to Ubuntu won't help, Ubuntu will package glibc 2.32 as well. The issue should be left open until it is actually fixed.

I found this bug report while researching the failure to build https://www.archlinux.org/packages/community/x86_64/io/ from source during a mass rebuild.

ales-tsurko commented 4 years ago

I agree this should be reopened as this is related not only to docker.

On my fork I fixed it using another method: https://github.com/ales-tsurko/io/commit/d51079cf47d3fb1596916387db5baf1b4e2afafe#diff-dc7a15f3aa6d0114411923f996d5592b3a8ae072793927425fcf97b6d55ff550

Can you try this patch and say whether it works for you?

eli-schwartz commented 4 years ago

Yes, removing the include makes the build compile cleanly for me too.

There is one call to sysctl() guarded by #if defined(CTL_HW) which should just not get compiled if it is unavailable due to sysctl.h not being included and thus defining neither sysctl() nor CTL_HW. It only seems to be getting the number of cpus here... sysconf() is used as a fallback. and should (seems to) work fine.

If you're going to remove the include, you should prune the dead code paths.

Alternatively, if there are non-linux platforms where you still want this (perhaps because the other potential implementations in libs/iovm/source/IoSystem.c aren't available on that platform?) the include could be guarded to not be used on Linux.

ales-tsurko commented 4 years ago

Oh, I sent a wrong patch. Can't find the exact commit, actually it looks like this (https://github.com/ales-tsurko/io/blob/b24aa430ed336ff1c7e218dfad4367517b20c607/libs/iovm/source/IoSystem.c#L25):

#if defined(HAVE_SYS_SYSCTL_H) && !defined(__GLIBC__)
#include <sys/sysctl.h>
#endif

As for the other platforms, on the fork I configured CI and Io passes all tests on Windows and macOS as well. There's an issue with Eerie on Windows, though. I'm still working on the update, but will open the PR soon.