I'm trying to run Qt5 framework through eglfs instead of X11 or wayland.
I'm trying to install Qt5 for qemuarm emualting Raspberry pi 3 based on yocto Rocko.
This is my bblayers.conf:
# POKY_BBLAYERS_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
POKY_BBLAYERS_CONF_VERSION = "2"
BBPATH = "${TOPDIR}"
SRCPATH = "/home/yocto/yocto"
BBFILES ?= ""
BBLAYERS ?= " \
${SRCPATH}/meta \
${SRCPATH}/meta-poky \
${SRCPATH}/meta-openembedded/meta-oe \
${SRCPATH}/meta-openembedded/meta-multimedia \
${SRCPATH}/meta-openembedded/meta-networking \
${SRCPATH}/meta-openembedded/meta-perl \
${SRCPATH}/meta-openembedded/meta-python \
${SRCPATH}/meta-qt5 \
${SRCPATH}/meta-raspberrypi \
${SRCPATH}/meta-security \
and this is my local.conf:
MACHINE ??= "qemuarm"
DL_DIR ?= "${TOPDIR}/../downloads"
DISTRO ?= "poky"
PACKAGE_CLASSES ?= "package_deb"
EXTRA_IMAGE_FEATURES ?= "debug-tweaks"
USER_CLASSES ?= "buildstats image-mklibs image-prelink"
PATCHRESOLVE = "noop"
BB_DISKMON_DIRS = "\
STOPTASKS,${TMPDIR},1G,100K \
STOPTASKS,${DL_DIR},1G,100K \
STOPTASKS,${SSTATE_DIR},1G,100K \
STOPTASKS,/tmp,100M,100K \
ABORT,${TMPDIR},100M,1K \
ABORT,${DL_DIR},100M,1K \
ABORT,${SSTATE_DIR},100M,1K \
ABORT,/tmp,10M,1K"
LICENSE_FLAGS_WHITELIST = "commercial"
CONF_VERSION = "1"
PREFERRED_VERSION_linux-raspberrypi = "4.%"
DISTRO_FEATURES_remove = "x11 wayland"
DISTRO_FEATURES_append = " systemd opengl pam ${DISTRO_FEATURES_LIBC}"
VIRTUAL-RUNTIME_init_manager = "systemd"
EXTRA_IMAGE_FEATURES += "package-management splash"
INHERIT+="toaster buildhistory"
CORE_IMAGE_EXTRA_INSTALL += "openssh"
ENABLE_UART="1"
#PACKAGECONFIG_append_qtbase = " accessibility eglfs fontconfig gles2 linuxfb"
################### QT ######################
QT_DEV_TOOLS = " \
qtbase-dev \
qtbase-mkspecs \
qtbase-plugins \
qtbase-tools \
qtserialport-dev \
qtserialport-mkspecs \
"
QT_TOOLS = " \
qtbase \
qtserialport \
"
FONTS = " \
fontconfig \
fontconfig-utils \
ttf-bitstream-vera \
"
TSLIB = " \
tslib \
tslib-conf \
tslib-calibrate \
tslib-tests \
tspress \
"
QT5_PKGS = " \
qt3d \
qtcharts \
qtdeclarative \
qtdeclarative-plugins \
qtdeclarative-qmlplugins \
qtgraphicaleffects \
qtlocation-plugins \
qtmultimedia \
qtquickcontrols2 \
qtsensors-plugins \
qtserialbus \
qtsvg \
qtwebsockets-qmlplugins \
qtvirtualkeyboard \
qtxmlpatterns \
"
QML_APPS = " \
qqtest \
"
CORE_IMAGE_EXTRA_INSTALL += " \
${FONTS} \
${QT_TOOLS} \
${QT5_PKGS} \
cinematicexperience \
"
I'm trying to build this image bitbake rpi-hwup-image
the problem is with qtbase, it fails with this error:
| ERROR: Feature 'opengl-desktop' was enabled, but the pre-condition '(config.win32 && !config.winrt && !features.opengles2 && (config.msvc || libs.opengl))
| || (!config.watchos && !config.win32 && libs.opengl)' failed.
|
| ERROR: The OpenGL functionality tests failed!
| You might need to modify the include and library search paths by editing QMAKE_INCDIR_OPENGL[_ES2],
| QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your platform.
Update
This problem is solved by uncommenting PACKAGECONFIG_append_qtbase and it has a typo so, it's been updated to be PACKAGECONFIG_append_pn-qtbase.
I added those lines too:
PACKAGECONFIG_append_pn-qemu-native = " sdl"
PACKAGECONFIG_append_pn-nativesdk-qemu = " sdl".
I comment out this line LICENSE_FLAGS_WHITELIST = "commercial".
but it fails again at qtbase build by this error (this is the tail of the log file) (I deleted the tmp folder and started bitbake rpi-hwup-image again but it went to the same error)
| cd windowflags/ && ( test -e Makefile || /home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/recipe-sysroot-native/usr/bin/qt5/qmake -o Makefile /home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/git/examples/widgets/widgets/windowflags/windowflags.pro -qtconf /home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/build/bin/qt.conf ) && make -f Makefile
| make[4]: Entering directory '/home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/build/examples/widgets/widgets/windowflags'
| compiling /home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/git/examples/widgets/widgets/windowflags/controllerwindow.cpp
| compiling /home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/git/examples/widgets/widgets/windowflags/previewwindow.cpp
| linking wiggly
| make[4]: Leaving directory '/home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/build/examples/widgets/widgets/wiggly'
| compiling /home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/git/examples/widgets/widgets/windowflags/main.cpp
| linking validators
| generating .moc/moc_predefs.h
| moc /home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/git/examples/widgets/widgets/windowflags/controllerwindow.h
| make[4]: Leaving directory '/home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/build/examples/widgets/widgets/validators'
| moc /home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/git/examples/widgets/widgets/windowflags/previewwindow.h
| compiling .moc/moc_controllerwindow.cpp
| compiling .moc/moc_previewwindow.cpp
| linking windowflags
| make[4]: Leaving directory '/home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/build/examples/widgets/widgets/windowflags'
| make[3]: Leaving directory '/home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/build/examples/widgets/widgets'
| make[2]: Leaving directory '/home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/build/examples/widgets'
| make[1]: Leaving directory '/home/yocto/yocto/build/RP3_Qt/tmp/work/armv5e-poky-linux-gnueabi/qtbase/5.9.3+gitAUTOINC+4d8ae444c2-r0/build/examples'
| ERROR: oe_runmake failed
| WARNING: exit code 1 from a shell command.
I found the solution according to this page.
The configuration part -at this page- says something about ommiting the tests part at this option -nomake tests, it's the same part that fails at the compiling stage of qtbase.
so after cleaning qtbase and adding this part to my local.conf
PACKAGECONFIG_remove_pn-qtbase = " tests gl"
gl is omitted too because we want to build qtbase for eglfs not for desktop.
Related
I want to get a little loading animation as long the Makefile compiles my .o files i saw a loading animation which switched between [|], [/], [-], [] and that is what i wanna implement now.
I tried to achieve that by using printf a Make variable and some ifeq and else ifeq conditions but that didn't worked somehow the if conditions are checked just once after the first call of the
$(OBJDIR)/%.o: rule
what i expect is that the stage of the loading box switches every time the $(OBJDIR)/%.o: rule is called or somehow timebased if there is an easy solution but i think its too complicated so i would stick to the first for now
Also its my first time asking here pls be patient and tell me how to improve my questions
that is the makefile
# **************************************************************************** #
# #
# ::: :::::::: #
# Makefile :+: :+: :+: #
# +:+ +:+ +:+ #
# By: pharbst <pharbst#student.42heilbronn.de +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2022/05/06 09:33:42 by pharbst #+# #+# #
# Updated: 2022/11/29 03:29:26 by pharbst ### ########.fr #
# #
# **************************************************************************** #
SHELL= /bin/bash
Black = $(shell echo -e "\033[0;30m")
FBlack = $(shell echo -e "\033[1;30m")
Red = $(shell echo -e "\033[0;31m")
FRed = $(shell echo -e "\033[1;31m")
Green = $(shell echo -e "\033[0;32m")
FGreen = $(shell echo -e "\033[1;32m")
Brown/Orange = $(shell echo -e "\033[0;33m")
FBrown/Orange = $(shell echo -e "\033[1;33m")
FYellow = $(shell echo -e "\033[1;33m")
Yellow = $(shell echo -e "\033[0;33m")
Blue = $(shell echo -e "\033[0;34m")
FBlue = $(shell echo -e "\033[1;34m")
Purple = $(shell echo -e "\033[0;35m")
FPurple = $(shell echo -e "\033[1;35m")
Cyan = $(shell echo -e "\033[0;36m")
FCyan = $(shell echo -e "\033[1;36m")
FWhite = $(shell echo -e "\033[1;37m")
White = $(shell echo -e "\033[0;37m")
RESET = $(shell echo -e "\033[0m")
TICK = $(shell echo -e "\xE2\x9C\x94")
PRONAME = libftio
NAME = libftio.a
CC = cc
CFLAGS = -Wall -Wextra -Werror -I includes -g
HEADER = ./includes/libftio.h
SRCDIR = ./src
OBJDIR = ./obj
FILES = ft_atoi.c \
ft_bzero.c \
ft_calloc.c \
ft_isalnum.c \
ft_isalpha.c \
ft_isascii.c \
ft_isdigit.c \
ft_isprint.c \
ft_memchr.c \
ft_memcmp.c \
ft_memcpy.c \
ft_memmove.c \
ft_memset.c \
ft_strchr.c \
ft_strlcat.c \
ft_strlcpy.c \
ft_strlen.c \
ft_strncmp.c \
ft_strnstr.c \
ft_strrchr.c \
ft_tolower.c \
ft_toupper.c \
ft_itoa.c \
ft_putchar_fd.c \
ft_putendl_fd.c \
ft_putnbr_fd.c \
ft_putstr_fd.c \
ft_split.c \
ft_strdup.c \
ft_strjoin.c \
ft_strtrim.c \
ft_substr.c \
ft_strmapi.c \
ft_striteri.c \
\
ft_lstnew.c \
ft_lstadd_front.c \
ft_lstsize.c \
ft_lstlast.c \
ft_lstadd_back.c \
ft_lstdelone.c \
ft_lstclear.c \
ft_lstiter.c \
ft_lstmap.c \
\
ft_bufferjoin.c \
ft_buffinit.c \
ft_chartostr.c \
ft_itohex.c \
ft_ptrtohex.c \
ft_strjoinchar.c \
ft_strjoinfree.c \
ft_strlower.c \
ft_strupper.c \
ft_uitoa.c \
ft_printf.c \
ft_printf_helper.c \
get_next_line.c \
ft_strcmp.c \
ft_free_split.c \
OBJS = $(addprefix $(OBJDIR)/, $(FILES:.c=.o))
OBJ_FLAG = 0
all: $(NAME)
$(NAME): header obj_header $(OBJS) linking_header
#ar rcs $(NAME) $(OBJS)
#printf "\b\b\b$(FGreen)[$(TICK)]\n$(RESET)"
$(OBJDIR)/%.o: $(SRCDIR)/*/%.c
#mkdir -p $(OBJDIR)
#$(CC) $(CFLAGS) -o $# -c $<
ifeq ($(OBJ_FLAG), 0)
#printf "\b\b\]"
#OBJ_FLAG=1
else ifeq ($(OBJ_FLAG), 1)
#printf "\b\b|]"
#OBJ_FLAG=2
else ifeq ($(OBJ_FLAG), 2)
#printf "\b\b/]"
#OBJ_FLAG=3
else ifeq ($(OBJ_FLAG), 3)
#printf "\b\b-]"
#OBJ_FLAG=0
endif
clean: header
#echo "$(FRed)Clean $(PRONAME)$(FGreen) [$(TICK)]"
#rm -rf $(OBJS)
#rm -rf $(OBJDIR)
#echo "$(RESET)"
fclean: header
#echo "$(FRed)FCleaning $(PRONAME)$(FGreen) [$(TICK)]"
#rm -rf $(OBJDIR)
#rm -rf $(NAME)
re: fclean all
header:
#echo "$(FBlue)====================$(FYellow)$(PRONAME)$(FBlue)====================$(RESET)"
obj_header:
#printf "$(FBlue)Compiling .o files $(FYellow)[-]"
linking_header:
#printf "\b\b\b$(FGreen)[$(TICK)]\n$(Green)Linking $(PRONAME) $(FYellow)[-]$(RESET)"
git: commit push
commit:
git commit -m "$(msg)"
push:
git push
update:
git pull
.PHONY: all clean fclean re
peter (btw how in the world was this handle not taken prior to 2022?), first off, you really need to go to gnu.org and read the make manual. This is not only recommended but vital if you want to make use of the build language and concepts behind make and its relatives.
Secondly, and this is where I jump ahead of the chapter How make reads a makefile which you should read first, make does not execute the ifeq's in the way you envision: if, ifeq etc. are only used in one first pass when parsing the makefile to decide which parts of the makefile are parsed and which ones are ignored (forever). When make runs over one of its conditionals, it only parses the true-route (if or else branch) and literally throws away all lines from the false-route. This means it is of no use in creating looping constructs or repeated runtime decisions where the various branches are elicited for execution by a dynamic logic predicate. In one word, the ifeq's in your example don't belong to the rule in which they seemingly are embedded but to the file as a whole.
That said, there is one more issue with your perception of make rules: they are executed by calling one extra shell process and therefore a completely fresh set of variables (exceptions: see the manual) per line of a recipe so an assignment like
#OBJ_FLAG=1
is ineffective as the process where this variable exists and has the value 1 lives only for this one line and is deleted immediately afterwards. (See .ONESHELL in the manual for an exemption)
The final upshot of all which I said here is that it is extremely hard to programmatically loop in make in parallel with the recipe execution. This simply never was in the focus of its development which aimed for maximum non-intrusiveness and side-stepping of the make process itself when some recipe process is runnnig. Adorning the build run with interactive elements is left to the user, i.e. to user-supplied programs which also would have to solve the concurrency problems of the 1:n stdout to compilation processes in a parallel make run. Maybe you can draw some inspirations from there: https://unix.stackexchange.com/questions/225179/display-spinner-while-waiting-for-some-process-to-finish
I have this layer configuration file in poky/meta-test/conf directory
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb"
${LAYERDIR}/recipes-*/*/*.bbappend
${LAYERDIR}/recipes-*/*.bb
${LAYERDIR}/recipes-*/*.bbappend ”
BBFILE_COLLECTIONS += “test”
BBFILE_PATTERN_test = “^${LAYERDIR}/”
BBFILE_PRIORITY_test = “13”
LAYERVERSION_test = “13”
And when I do
source oe-init-build-env build
bitbake core-image-minimal //error at this
error
ERROR: ParseError at /home/ubuntu/Desktop/embedded_Emdevor/my/my/poky/meta-test/conf/layer.conf:5: unparsed line: '${LAYERDIR}/recipes-*/*/*.bbappend'
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend \
${LAYERDIR}/recipes-*/*.bb \
${LAYERDIR}/recipes-*/*.bbappend ”
I'm trying to run the below command in a script and it seems it's not adding any text layout to the video, I'm sure I didn't it before and it was fine.
My question is, do I need to set up X11 environment in order to use dynamictext or text filters?
Thanks in advance.
/usr/bin/melt \
"/var/www/html/test/nkLcBPkebo/t-1.mp4" \
-audio-track \
"/var/www/html/test/nkLcBPkebo/t-1_sound.mp4" \
-attach-track \
"text:This is my best video" \
-0 \
in=0 out=0 fgcolour="#004fed" bgcolour=0 olcolour="#fff200" outline=3 pad="50x0" size=80 weight=700 style="italic" halign="center" valign="top" family="Ubuntu" \
-profile hdv_720_25p -progress \
-consumer avformat:"/var/www/html/test/nkLcBPkebo/1.mp4" \
vcodec="libx264" vb="5000k" acodec="aac" ab="128k" frequency=44100 deinterlace=1
I think I found the issue! it's was all about the order of the parameters :)
Having the text right after the video (before the audio) should fix it
/usr/bin/melt \
"/var/www/html/test/nkLcBPkebo/t-1.mp4" \
-attach-track \
"text:This is my best video" \
-0 \
in=0 out=0 fgcolour="#004fed" bgcolour=0 olcolour="#fff200" outline=3 pad="50x0" size=80 weight=700 style="italic" halign="center" valign="top" family="Ubuntu" \
-audio-track \
"/var/www/html/test/nkLcBPkebo/t-1_sound.mp4" \
-profile hdv_720_25p -progress \
-consumer avformat:"/var/www/html/test/nkLcBPkebo/1.mp4" \
vcodec="libx264" vb="5000k" acodec="aac" ab="128k" frequency=44100 deinterlace=1
I would like to create a string of index and value pairs. This is to be used in dialog menu.
declare -r -a arr=(
piano
table
chair
)
dialog \
--backtitle "Launcher" \
--title "App" \
--ok-label 'Select' \
--cancel-label "Back" \
--menu "Select an application" \
$dialog_height $dialog_width 4 \
"1" "piano" \
"2" "table" \
"3" "chair"
So I'm looking to have the:
"1" "piano" \
"2" "table" \
"3" "chair"
generated automatically from array.
There's a similar question pass an array to dialog menu I tried what's there I couldn't get it to work for me.
To auto-generate the tags 1, 2, 3 in front of every array entry, use
items=(piano table chair)
taggedItems=()
for ((i=1; i<="${#items[#]}"; ++i)); do
taggedItems+=("$i" "${items[i-1]}")
done
# then use "${taggedItems[#]}"
Opposed to your linked awk solution, this works with arbitrary items that may contain spaces, special symbols like * and even linebreaks.
declare -a arr=(
''
piano
table
chair
)
unset 'arr[0]'
declare -ar arr
# Remove the echo below once ready for the fun.
echo dialog \
--backtitle "Launcher" \
--title "App" \
--ok-label 'Select' \
--cancel-label "Back" \
--menu "Select an application" \
$dialog_height $dialog_width 4 \
$(for i in "${!arr[#]}"; do echo "$i" "${arr[i]}"; done)
OPTIONS=(1 "table"
2 "piano"
3 "......")
dialog \
--backtitle "Launcher" \
--title "App" \
--ok-label 'Select' \
--cancel-label "Back" \
--menu "Select an application" \
$dialog_height $dialog_width 4 \
"${OPTIONS[#]}" \
2>&1 >/dev/tty
There are two ways, using simple array:
#!/bin/bash
declare -r -a arr=(
piano
table
chair
)
options=$(printf '%s\n' "${arr[#]}" | awk '{print v++,$arr}')
dialog \
--backtitle "Test" \
--title "Test" \
--menu "Test" \
0 0 4 \
$options \
2>&1 >/dev/tty
Or with associative array:
#!/bin/bash
declare -r -A arr=(
piano
table
chair
)
options=$(printf '%s\n' "${!arr[#]}" | awk '{print v++,$arr}')
dialog \
--backtitle "Test" \
--title "Test" \
--menu "Test" \
0 0 4 \
$options \
2>&1 >/dev/tty
To start menu numbers at 1:
#!/bin/bash
declare -r -a arr=(
piano
table
chair
)
options=$(printf '%s\n' "${arr[#]}" | awk -v v=1 '{print v++,$arr}')
dialog \
--backtitle "Test" \
--title "Test" \
--menu "Test" \
0 0 4 \
$options \
2>&1 >/dev/tty
To use both key and value of associative array in menu:
#!/bin/bash
declare -r -A arr=(
[piano]=piano
[table]=mesa
[chair]=cadeira
)
options=$(printf "%s\n" "${!arr[#]} " "${arr[#]}")
dialog \
--backtitle "Test" \
--title "Test" \
--menu "Test" \
0 0 4 \
$options \
2>&1 >/dev/tty
Correct answer works both with normal and associative arrays of entries, using numerical index or associative key as menu key:
Normal array of menu entries, using numerical index as menu key:
#!/usr/bin/env bash
arr=(
piano
table
chair
)
options=()
for k in "${!arr[#]}"; do
options+=( "$k" "${arr[$k]}" )
done
dialog \
--backtitle "Test" \
--title "Test" \
--menu "Test" \
0 0 4 \
"${options[#]}" \
>/dev/tty 2>&1
Full example with associative array:
#!/usr/bin/env bash
declare -A assoc=(
[p]=piano
[t]=table
[c]=chair
)
options=()
for k in "${!assoc[#]}"; do
options+=("$k" "${assoc[$k]}")
done
choice="$(
dialog \
--backtitle "Test" \
--title "Test" \
--menu "Test" \
0 0 4 \
"${options[#]}" \
2>&1 >/dev/tty
)"
clear
case $choice in
t)
printf %s\\n "Let's set the table."
;;
p)
printf %s\\n "Let's play piano."
;;
c)
printf %s\\n "Let's sit dow."
;;
*)
printf %s\\n "Let's decide later."
;;
esac
It's taking about 15 minutes to insert a 500MB ndjson file with 100,000 rows into MS SQL Server table. I am running Spark locally on a machine with good specs - 32GB RAM, i9-10885H CPU with 8 cores. I doubt that the machine is being used to its full capabilities. Here is what I am trying.
master = "local[16]"
conf = SparkConf() \
.setAppName(appName) \
.set("spark.driver.memory", "16g") \
.set("spark.executor.memory", "1g") \
.set('spark.executor.cores', '5') \
.set("spark.driver.extraClassPath","./mssql-jdbc-9.2.1.jre11.jar") \
.setMaster(master)
sc = SparkContext(conf=conf)
sqlContext = SQLContext(sc)
spark = sqlContext.sparkSession
def insert_into_ss(start):
for i in range(start, len(files)):
item = files[i]
print(item)
start = datetime.now()
spark_df = sqlContext.read.json(upload_dir + '/' +item)
spark_df = spark_df.select([col(c).cast("string") for c in spark_df.columns])
print('Casting time', datetime.now() - start)
spark_df.write.mode("append") \
.format("jdbc") \
.option("url", url) \
.option("dbtable", table) \
.option("batchsize", 20000) \
.option("reliabilityLevel", 'NO_DUPLICATES') \
.option("tableLock", 'true') \
.option("numPartitions", 16) \
.option("bulkCopyTimeout", 600000) \
.option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver") \
.save()
end = datetime.now()
print(end-start)
insert_into_ss()